/*
 * This file is part of quickReminder, a software for gamers
 *
 * Copyright (C) 2006-2008 Lucas Romero
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Threading;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Diagnostics;
using System.Xml.Serialization;
using System.ComponentModel;

namespace UserNotifier
{
    public class OSDWarnModule : WarnModule
    {
        private Image m_WarnImage;
        private int m_Spacing = 5;

        public override WarnModuleTypes Type
        {
            get { return WarnModuleTypes.OSDWarnModule; }
        }
        //private Graphics g = null;
        private string m_WarnMessage = string.Empty;
        private TimerCollection m_Timers = new TimerCollection();
        private IntPtr m_WindowHandle = IntPtr.Zero;

        private bool m_IgnoreWarnings = false;

        public override string Description
        {
            get
            {
                return Info.OSDDesc;
            }
        }

        [Browsable(false)]
        [XmlIgnore]
        public bool IgnoreWarnings
        {
            get { return m_IgnoreWarnings; }
            set { m_IgnoreWarnings = value; }
        }

        private Process m_GameProcess = null;

        [Browsable(false)]
        [XmlIgnore]
        public Process GameProcess
        {
            get { return m_GameProcess; }
            set
            { 
                m_GameProcess = value;
                
            }
        }
        StringCollection WarnMessages = new StringCollection();
        private bool m_DrawWarnImage = true;

        public bool DrawWarnImage
        {
            get { return m_DrawWarnImage; }
            set { m_DrawWarnImage = value; }
        }
        private Font m_OSDFont = new Font("Tahoma", 30);

        [XmlIgnore]
        public Font OSDFont
        {
            get { return m_OSDFont; }
            set { m_OSDFont = value; }
        }
        private Color m_OSDColor = Color.Red;

        [XmlIgnore]
        public Color OSDColor
        {
            get { return m_OSDColor; }
            set { m_OSDColor = value; }
        }

        [Browsable(false)]
        public string XmlOSDColor
        {
            get
            {
                return TypeDescriptor.GetConverter(m_OSDColor.GetType()).ConvertToInvariantString(m_OSDColor);
                //return (Font)TypeDescriptor.GetConverter(typeof(Font)).ConvertFromString("Microsoft Sans Serif; 8,25pt");
            }
            set
            {
                m_OSDColor = (Color)TypeDescriptor.GetConverter(m_OSDColor.GetType()).ConvertFromInvariantString(value);
            }
        }

        [Browsable(false)]
        public string XmlOSDFont
        {
            get
            {
                return TypeDescriptor.GetConverter(m_OSDFont.GetType()).ConvertToInvariantString(m_OSDFont);
                //return (Font)TypeDescriptor.GetConverter(typeof(Font)).ConvertFromString("Microsoft Sans Serif; 8,25pt");
            }
            set
            {
                m_OSDFont = (Font)TypeDescriptor.GetConverter(m_OSDFont.GetType()).ConvertFromInvariantString(value);
            }
        }

        private GraphicsPath m_WarnPath = new GraphicsPath();

        public OSDWarnModule(int interval)
            : base(interval)
        {
            InitImage();
        }

        public OSDWarnModule()
            : base()
        {
            InitImage();
        }

        private void InitImage()
        {
            System.Resources.ResourceManager res = new System.Resources.ResourceManager("UserNotifier.images", this.GetType().Assembly);
            m_WarnImage = (Image)res.GetObject("messagebox_warning");
        }

        /*public override void InitDelegate()
        {
 	         Thread.CurrentThread.Priority = ThreadPriority.Highest;
        }*/

        /*public override void CleanupDelegate()
        {
            if (g != null)
                g.Dispose();
        }*/

        protected override void Warn()
        {
            //DateTime start = DateTime.Now;
            if (m_GameProcess != null)
            {
                if (!m_GameProcess.HasExited)
                {
                    m_GameProcess.Refresh();
                }
                if (!m_GameProcess.HasExited)
                    DrawOSD(m_GameProcess.MainWindowHandle);
            }
            //Trace.WriteLine(DateTime.Now.Subtract(start).TotalMilliseconds.ToString());
        }

        private void DrawOSD(IntPtr target)
        {
            Graphics g = Graphics.FromHwnd(target);
            if (/*!m_GameProcess.HasExited && */g != null)
            {
                g.SmoothingMode = SmoothingMode.HighSpeed;
                g.InterpolationMode = InterpolationMode.Low;
                //SizeF strSizeF = g.MeasureString(m_WarnMessage, m_OSDFont);
                if (m_DrawWarnImage)
                    g.DrawImageUnscaled(m_WarnImage, 0, 0/*(int)Math.Max(0,(strSizeF.Height - m_WarnImage.Height) / 2)*/);

                lock (m_WarnPath)
                {
                    g.FillPath(new SolidBrush(m_OSDColor), m_WarnPath);
                }
                g.Dispose();
            }
        }


        /*public override void Test()
        {
            string testmsg = "Just\nsome\ntest";
            Monitor.Enter(m_WarnPath);
            GraphicsPath old = (GraphicsPath)m_WarnPath.Clone();
            m_WarnPath.Reset();
            m_WarnPath.AddString(testmsg, m_OSDFont.FontFamily, (int)m_OSDFont.Style, m_OSDFont.Size, new Point(0, 0), new StringFormat());
            if (m_DrawWarnImage)
            {
                Matrix m = new Matrix();
                m.Translate(m_WarnImage.Width + m_Spacing, 0);
                m_WarnPath.Transform(m);
            }
            Monitor.Exit(m_WarnPath);
            DrawOSD(LucasCode.Win32.User32.GetForegroundWindow());
            m_WarnPath = old;
            //UpdateWarnString();
            //throw new NotSupportedException("The ConsoleWarnModule does not yet support testing!");
        }*/

        public override void Test()
        {
            throw new NotSupportedException(Info.TestingNotSupported);
        }


        /*public void AddWarning(string Warning)
        {
            if (m_IgnoreWarnings)
                return;
            if (!WarnMessages.Contains(Warning))
            {
                WarnMessages.Add(Warning);
                UpdateWarnString();
            }
        }
        private void RemoveWarning(object Warning)
        {
            RemoveWarning((string)Warning);
        }
        public void AddWarning(string Warning, int timeout)
        {
            if (m_IgnoreWarnings)
                return;
            AddWarning(Warning);
            m_Timers.NewTimer(Warning, new TimerCallback(RemoveWarning), timeout);
            //timers.Add(new WarnTimer(Warning, new TimerCallback(RemoveWarning), timeout));
        }
        public void RemoveWarning(string Warning)
        {
            if (WarnMessages.Contains(Warning))
            {
                WarnMessages.Remove(Warning);
                UpdateWarnString();
            }
        }*/
        protected override void EventsChanged(WarnEvents newActiveEvents)
        {
            UpdateWarnString(newActiveEvents);
            base.EventsChanged(newActiveEvents);
        }

        public void UpdateWarnString(WarnEvents newActiveEvents)
        {
            try
            {
                lock (m_WarnPath)
                    m_WarnPath.Reset();
                if (newActiveEvents != WarnEvents.None)
                {
                    StringBuilder b = new StringBuilder();
                    if ((newActiveEvents & WarnEvents.NoAequitas) != WarnEvents.None)
                    {
                        b.AppendLine("No aequitas running!");
                    }
                    if ((newActiveEvents & WarnEvents.NoReplay) != WarnEvents.None)
                    {
                        b.AppendLine("No demo recording!");
                    }
                    if ((newActiveEvents & WarnEvents.TakeStatus) != WarnEvents.None)
                    {
                        b.AppendLine("Take status-screenshot!");
                    }
                    if ((newActiveEvents & WarnEvents.RestartReplay) != WarnEvents.None)
                    {
                        b.AppendLine("Teams changed, record new demo?");
                    }
                    if ((newActiveEvents & WarnEvents.LowDiskspace) != WarnEvents.None)
                    {
                        b.AppendLine("Low on disc space!");
                    }
                    m_WarnMessage = b.ToString().Trim();
                    lock (m_WarnPath)
                    {
                        try
                        {
                            m_WarnPath.Reset();
                            m_WarnPath.AddString(m_WarnMessage, m_OSDFont.FontFamily, (int)m_OSDFont.Style, m_OSDFont.Size, new Point(0, 0), new StringFormat());
                            if (m_DrawWarnImage)
                            {
                                Matrix m = new Matrix();
                                m.Translate(m_WarnImage.Width + m_Spacing, 0);
                                m_WarnPath.Transform(m);
                            }
                        }
                        catch { }
                    }
                }
            }
            catch (System.Exception e)
            {
            	Trace.WriteLine("Error at UpdateWarnString:" + e.Message);
            }
            
        }
    }

    
}
